<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>自定义指令</title>
    <!-- 引入Vue.js -->
    <script src="../js/vue.js"></script>
  </head>
  <body>
    <!-- 
      需求1：定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
      需求2：定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点
     -->
    <!-- 准备好一个容器(模板) -->
    <div id="root">
      <h2>{{name}}</h2>
      <h2>当前的n值是:<span v-text="n"></span></h2>
      <h2>放大十倍后的n值是:<span v-big="n"></span></h2>
      <!-- <h2>放大十倍后的n值是:<span v-big-number="n"></span></h2> -->
      <!-- 当指令名较长时,中间使用"-"连接 -->
      <button @click="n++">点我n++</button>
      <hr />
      默认获取焦点的input元素是:<input type="text" v-fbind:value="n" />
    </div>

    <div id="root2">
      默认获取焦点的input元素是:<input type="text" v-fbind:value="n" />
    </div>
  </body>
  <script>
    // 全局自定义指定  在任意一个Vue实例中都能使用
    // 1.完整写法
    Vue.directive("fbind", {
      bind(element, binding) {
        element.setAttribute(binding.arg, binding.value);
      },
      inserted(element, binding) {
        element.focus();
      },
      update(element, binding) {
        element.setAttribute(binding.arg, binding.value);
      },
    });
    // 2.简化写法
    Vue.directive('big', function (element, binding) {
      element.innerText = binding.value * 10;
    });

    const vm = new Vue({
      el: "#root",
      data: {
        // data数据发生改变会引起模板的重新解析
        name: "张三",
        n: 1,
      },
      // 自定义指令
      directives: {
        // 自定义指令名不需要加v-前缀 函数接收两个参数
        big(element, binding) {
          /*big函数何时会被调用？
          1.指令与元素成功绑定时(此时元素还未添加到页面中) 
          2.指令所在的模板被重新解析时 */
          console.log(element, binding);
          // element:绑定v-big指令元素的真实DOM  binging:绑定对象 binding.value:绑定的值
          console.log("big", this); // this指向window
          // 修改绑定的数值
          element.innerText = binding.value * 10;
        },
        // 如果对象的key中出现"-"必须将键名写为字符串格式
        /* "big-number"(element,binding){
          element.innerText = binding.value * 10;
        } */

        // 使用简化写法将bind()和update() 合并为一个函数,缺少了inserted()函数
        /* fbind(element, binding) {
          console.log(element, binding);
          // element.value = binding.value;
          // 适用于 v-fbind绑定任意属性 binding.arg:绑定的属性名
          element.setAttribute(binding.arg, binding.value);
          // element.focus(); 不奏效
          // fbind第一次执行时元素还未渲染到页面中 .focus()不奏效
        }, */
        // 完整写法
        fbind: {
          // bind() 指令与元素绑定成功但还未添加到页面中时调用
          bind(element, binding) {
            console.log("bind", this); // 注意：this指向window
            // 指令与元素绑定成功时为元素设置属性
            element.setAttribute(binding.arg, binding.value);
          },
          // inserted() 指令所在元素被插入页面时被调用
          inserted(element, binding) {
            // 当元素被插入到页面后获取元素焦点
            element.focus();
          },
          // update() 指令所在的模板被重新解析时调用
          update(element, binding) {
            element.setAttribute(binding.arg, binding.value);
          },
        },
      },
    });

    // 在vm实例对象中创建的自定义指令为局部指令,只能在当前实例对象中使用不能再另一个实例对象中使用
    new Vue({
      el: "#root2",
      data: {
        n: 1,
      },
    });
  </script>
</html>
